using System;
using System.Drawing;
using System.Net;
using System.Windows.Forms;
using SynoManager.GUI;

namespace SynoManager.DownloadStation
{
    /// <summary>
    /// Base interface for all DownloadStation Plugins.
    /// </summary>
    public interface IDownloadStationPlugin
    {
        /// <summary>
        /// Initializes the plugin with the specified service.
        /// </summary>
        /// <param name="service">DownloadStationService on which the service works</param>
        void Initialize(DownloadStationService service);
        /// <summary>
        /// Close the plugin
        /// </summary>
        void Close();
    }

    /// <summary>
    /// Interface that can be implemented by <see cref="IDownloadStationPlugin">plugins</see> that provide a preference panel.
    /// </summary>
    public interface IDownloadStationPreferencePanelPlugin : IDownloadStationPlugin
    {
        /// <summary>
        /// Gets the <see cref="PreferencesPanel" />.
        /// </summary>
        PreferencesPanel PreferencePanel { get; }
        /// <summary>
        /// Gets the text for the node in the navigation tree.
        /// </summary>
        string PreferenceNodeText { get; }
        /// <summary>
        /// Gets the image for the node in the navigation tree.
        /// </summary>
        Image PreferenceNodeImage { get; }
    }

    /// <summary>
    /// Interface that can be implemented by plugins that handle a certain filetype (e.g. .torrent, .txt, .nzb, etc.)
    /// </summary>
    /// <seealso cref="OpenDownloadFileDialog"/>
    public interface IDownloadFileHandlerPlugin : IDownloadStationPlugin
    {
        /// <summary>
        /// Gets the file mask of files that this plugin can handle (e.g. '*.txt' or '*.torrent')
        /// </summary>
        /// <seealso cref="OpenDownloadFileDialog"/>
        string Filter { get; }
        /// <summary>
        /// Gets the description for the file type.
        /// </summary>
        /// <seealso cref="OpenDownloadFileDialog"/>
        string FileTypeDescription { get; }
        /// <summary>
        /// Get wether to display this item in the 'All downloadable files' item in the <seealso cref="OpenDownloadFileDialog"/>.
        /// </summary>
        bool IncludeInAllFiles { get; }
        /// <summary>
        /// Process a file.
        /// </summary>
        /// <param name="args">File arguments.</param>
        void Process(ProcessFileArgs args);
        /// <summary>
        /// Returns true if this plugin can process the specified file.
        /// </summary>
        /// <param name="path">Path to the file.</param>
        /// <returns>True if the plugin can process the file</returns>
        bool CanProcess(string path);
        /// <summary>
        /// Directly process the file.
        /// </summary>
        /// <remarks>This method is called when the user selects a file handler in the <see cref="OpenDownloadFileDialog" /></remarks>
        /// <param name="path">File path.</param>
        void CreateTask(string path);
    }

    /// <summary>
    /// Struct that contains the processing info for a file.
    /// </summary>
    /// <remarks>This struct is generated in <see cref="DownloadStationService.AddFile(string)" /> and 
    /// then passed to all <see cref="IDownloadFileHandlerPlugin" />s.</remarks>
    public class ProcessFileArgs
    {
        private readonly string path;
        private bool cancel;
        private bool processed;

        /// <summary>
        /// Initializes a new instance of the <see cref="ProcessFileArgs"/> struct.
        /// </summary>
        /// <param name="path">The path to the file.</param>
        public ProcessFileArgs(string path)
        {
            this.path = path;
            this.cancel = false;
            this.processed = false;
        }

        /// <summary>
        /// Gets the path to the file.
        /// </summary>
        public string Path
        {
            get { return path; }
        }

        /// <summary>
        /// Cancel further processing of the file. (if set it will not be passed to any other plugins).
        /// </summary>
        public bool Cancel
        {
            get { return cancel; }
            set { cancel = value; }
        }

        /// <summary>
        /// Mark the file as processed.
        /// </summary>
        public bool Processed
        {
            get { return processed; }
            set { processed = value; }
        }
    }

    /// <summary>
    /// Struct that contains the processing info for a url.
    /// </summary>
    /// <remarks>This struct is generated in <see cref="DownloadStationService.AddUrl(string)" /> and 
    /// then passed to all plugins.</remarks>
    /// <seealso cref="IDownloadUrlHandlerPlugin"/>
    /// <seealso cref="IDownloadUrlProtocolHandlerPlugin"/>
    /// <seealso cref="IDownloadWebHandlerPlugin"/>
    public class ProcessUrlArgs
    {
        private Uri url;
        private bool cancel;
        private bool processed;
        private HttpWebResponse response;

        /// <summary>
        /// Initializes a new instance of the <see cref="ProcessUrlArgs"/> struct.
        /// </summary>
        /// <param name="url">The URL.</param>
        public ProcessUrlArgs(string url)
        {
            this.url = new Uri(url);
            processed = false;
            cancel = false;
            response = null;
        }

        /// <summary>
        /// Gets the Url.
        /// </summary>
        public Uri Url
        {
            get { return url; }
            set { url = value; }
        }

        /// <summary>
        /// Cancel further processing of the file. (if set it will not be passed to any other plugins).
        /// </summary>
        public bool Cancel
        {
            get { return cancel; }
            set { cancel = value; }
        }

        /// <summary>
        /// Gets or sets the response for the HEAD request.
        /// </summary>
        public HttpWebResponse Response
        {
            get { return response; }
            set { response = value; }
        }

        /// <summary>
        /// Mark the file as processed.
        /// </summary>
        public bool Processed
        {
            get { return processed; }
            set { processed = value; }
        }
    }

    /// <summary>
    /// Interface that can be implemented by plugins that handle a certain download protocol (e.g. ed2k:// bittorrent://, etc.)
    /// </summary>
    public interface IDownloadUrlProtocolHandlerPlugin : IDownloadStationPlugin
    {
        /// <summary>
        /// Gets the protocol prefix
        /// </summary>
        string ProtocolPrefix { get; }
        /// <summary>
        /// Process the URL.
        /// </summary>
        /// <param name="args">URL argumens.</param>
        void Process(ProcessUrlArgs args);
    }

    /// <summary>
    /// Interface that can be implemented by plugins that can handle url downloads (and add credentials, rewrite URL's, etc.)
    /// </summary>
    public interface IDownloadUrlHandlerPlugin : IDownloadStationPlugin
    {
        /// <summary>
        /// Process the URL.
        /// </summary>
        /// <param name="args">URL argumens.</param>
        void Process(ProcessUrlArgs args);
    }

    /// <summary>
    /// Interface that can be implemented by plugins that can process an URL to retrieve the real tasks.
    /// </summary>
    public interface IDownloadWebHandlerPlugin : IDownloadStationPlugin
    {
        /// <summary>
        /// Process the URL.
        /// </summary>
        /// <param name="args">URL argumens.</param>
        void Process(ProcessUrlArgs args);
    }

    /// <summary>
    /// Interface that can be implemented by plugins that want to keep track of Download Tasks
    /// </summary>
    public interface IDownloadTaskPlugin : IDownloadStationPlugin
    {
        /// <summary>
        /// Function that is called when a new <see cref="DownloadTask" /> is added to the Download Station.
        /// </summary>
        /// <remarks>Called by <seealso="DownloadStationPluginManager.OnTaskAdded(DownloadTask)" />.</remarks>
        /// <param name="task">Newly added <see cref="DownloadTask" />.</param>
        void OnTaskAdded(DownloadTask task);
        /// <summary>
        /// Function that is called when a <see cref="DownloadTask" /> was updated on the Download Station.
        /// </summary>
        /// <remarks>Called by <seealso="DownloadStationPluginManager.OnTaskUpdate(DownloadTask)" />.</remarks>
        /// <param name="task">Updated <see cref="DownloadTask" />.</param>
        void OnTaskUpdate(DownloadTask task);
        /// <summary>
        /// Function that is called when the <seealso cref="DownloadTask.State" /> of a <see cref="DownloadTask" /> changed on the Download Station.
        /// </summary>
        /// <remarks>Called by <seealso="DownloadStationPluginManager.OnTaskStateChange(DownloadTask)" />.</remarks>
        /// <param name="task">Changed <see cref="DownloadTask" />.</param>
        void OnTaskStateChange(DownloadTask task);
        /// <summary>
        /// Function that is called when a <see cref="DownloadTask" /> was removed on the Download Station.
        /// </summary>
        /// <remarks>Called by <seealso="DownloadStationPluginManager.OnTaskRemoved(DownloadTask)" />.</remarks>
        /// <param name="task">Removed <see cref="DownloadTask" />.</param>
        void OnTaskRemoved(DownloadTask task);
    }
}
